`timescale 1ns / 1ps

`include "data_width.vh"

module initial_const #(parameter
    DST_ID_DWIDTH = `DST_ID_DWIDTH,
    EDGE_OFF_DWIDTH = `EDGE_OFF_DWIDTH,
    SRC_ID_DWIDTH = `SRC_ID_DWIDTH,
    EDGE_INFO_ADDR_ST = `EDGE_INFO_ADDR_ST,
    VERTEX_MASK_WIDTH = `VERTEX_MASK_WIDTH,
    MEM_AWIDTH = `MEM_AWIDTH,
    VERTEX_PIPE_NUM_WIDTH = `VERTEX_PIPE_NUM_WIDTH
) (
    input                                                       clk,
    input                                                       front_rst,
    input                                                       ctrl_start,
    input [31 : 0]                                              front_vertex_num,
    input [31 : 0]                                              front_edge_num,
    
    output reg                                                  rst,
    output reg [DST_ID_DWIDTH - 1 : 0]                          dst_id_ed,
    output reg [DST_ID_DWIDTH - 1 : 0]                          vertex_num,
    output reg [EDGE_OFF_DWIDTH - 1 : 0]                        edge_off_ed,
    output reg [MEM_AWIDTH - 1 : 0]                             edge_off_addr_ed,
    output reg [MEM_AWIDTH - 1 : 0]                             edge_info_addr_ed,
    output reg [EDGE_OFF_DWIDTH - VERTEX_MASK_WIDTH - 1 : 0]    mem_edge_ed,
    output reg                                                  para_valid);

    reg [DST_ID_DWIDTH - 1 : 0]                          dst_id_ed_ini;
    reg [DST_ID_DWIDTH - 1 : 0]                          vertex_num_ini;
    reg [EDGE_OFF_DWIDTH - 1 : 0]                        edge_off_ed_ini;
    reg [MEM_AWIDTH - 1 : 0]                             edge_off_addr_ed_ini;
    reg [MEM_AWIDTH - 1 : 0]                             edge_info_addr_ed_ini;
    reg [EDGE_OFF_DWIDTH - VERTEX_MASK_WIDTH - 1 : 0]    mem_edge_ed_ini;
    reg                                                  para_valid_ini;


    // load parameter
    always @ (posedge clk) begin
        if (ctrl_start) begin
            // dst_id_ed should match with vertex_pipe_num.
            dst_id_ed_ini           <= front_vertex_num - 1 - ((front_vertex_num - 1) & {{(32 - VERTEX_PIPE_NUM_WIDTH){1'b0}}, {VERTEX_PIPE_NUM_WIDTH{1'b1}}});
            // other signal should match with edge_pipe_number.
            vertex_num_ini          <= front_vertex_num;
            edge_off_addr_ed_ini    <= ((front_vertex_num >> 5) + |(front_vertex_num & 32'h0000001f) - 1) << 7;
            edge_info_addr_ed_ini   <= (((front_edge_num >> 5) + |(front_edge_num & 32'h0000001f) - 1) << 7) + EDGE_INFO_ADDR_ST;
            edge_off_ed_ini         <= front_edge_num - 1;
            mem_edge_ed_ini         <= (front_edge_num >> 5) + |(front_edge_num & 32'h0000001f) - 1;
            para_valid_ini          <= 1'b1;
        end
    end

    // transfer paramater
    always @ (posedge clk) begin
        if (front_rst) begin
            rst                 <= 1'b1;
            dst_id_ed           <= 0;
            vertex_num          <= 0;
            edge_off_ed         <= 0;
            edge_off_addr_ed    <= 0;
            edge_info_addr_ed   <= 0;
            mem_edge_ed         <= 0;
            para_valid          <= 0;
        end
        else begin
            rst                 <= 1'b0;
            dst_id_ed           <= dst_id_ed_ini;
            vertex_num          <= vertex_num_ini;
            edge_off_ed         <= edge_off_ed_ini;
            edge_off_addr_ed    <= edge_off_addr_ed_ini;
            edge_info_addr_ed   <= edge_info_addr_ed_ini;
            mem_edge_ed         <= mem_edge_ed_ini;
            para_valid          <= para_valid_ini;
        end
    end

endmodule